﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using daq_test_cs;
using static daq_test_cs.DAQ217Wrapper;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace daq_test_cs
{
    public static class IntPtrExtensions
    {
        public static byte[] IntPtrToByteArray(IntPtr ptr, int length)
        {
            var array = new byte[length];
            Marshal.Copy(ptr, array, 0, length);
            return array;
        }
    }

    public class Program
    {
        // 通用设备测试函数
        public static void TestDevice(DeviceType deviceType)
        {
            Console.WriteLine($"=== 开始测试 {deviceType} 设备 ===");
            
            DeviceManager deviceManager = null;
            try
            {
                // 创建设备管理器
                deviceManager = new DeviceManager(deviceType);
                
                // 连接设备
                if (!deviceManager.ConnectDevice())
                {
                    Console.WriteLine($"{deviceType} 设备连接失败");
                    return;
                }
                Thread.Sleep(1000);

                if(!deviceManager.StopCollection())
                {
                    Console.WriteLine($"{deviceType} 停止采集失败");
                    return;
                }
                Thread.Sleep(3000);

                // 获取设备SN号
                IntPtr device = deviceManager.GetDevice();
                if (device != IntPtr.Zero)
                {
                    StringBuilder snBuffer = new StringBuilder(17);
                    bool snResult = false;
                    string sn = string.Empty;
                    int retryCount = 0;
                    const int maxRetries = 5;
                    
                    // 最多重试5次获取SN
                    while (retryCount < maxRetries)
                    {
                        snBuffer.Clear();
                        snResult = false;
                        
                        switch (deviceType)
                        {
                            case DeviceType.DAQ125:
                                snResult = DAQ125Wrapper.DAQ125_ProductTestGetSN(device, snBuffer, 17);
                                break;
                            case DeviceType.DAQ206:
                                snResult = DAQ206Wrapper.DAQ206_ProductTestGetSN(device, snBuffer, 17);
                                break;
                            case DeviceType.DAQ207:
                                snResult = DAQ207Wrapper.DAQ207_ProductTestGetSN(device, snBuffer, 17);
                                break;
                            case DeviceType.DAQ216:
                                snResult = DAQ216Wrapper.DAQ216_ProductTestGetSN(device, snBuffer, 17);
                                break;
                            case DeviceType.DAQ217:
                                snResult = DAQ217Wrapper.DAQ217_ProductTestGetSN(device, snBuffer, 17);
                                break;
                            case DeviceType.DAQ322:
                                snResult = DAQ322Wrapper.DAQ322_ProductTestGetSN(device, snBuffer, 17);
                                break;
                        }
                        
                        if (snResult)
                        {
                            sn = snBuffer.ToString().Trim();
                            // 检查SN是否有效（不为空且不为"0"）
                            if (!string.IsNullOrEmpty(sn) && sn != "0")
                            {
                                Console.WriteLine($"{deviceType} 设备SN号: {sn}");
                                break;
                            }
                        }
                        
                        retryCount++;
                        if (retryCount < maxRetries)
                        {
                            Console.WriteLine($"{deviceType} 获取设备SN号失败，正在重试... ({retryCount}/{maxRetries})");
                            Thread.Sleep(100); // 等待100ms后重试
                        }
                    }
                    
                    if (retryCount >= maxRetries)
                    {
                        Console.WriteLine($"{deviceType} 获取设备SN号失败，已达到最大重试次数");
                    }
                }
                
                // 配置设备
                if (!deviceManager.ConfigureDevice())
                {
                    Console.WriteLine($"{deviceType} 设备配置失败");
                    return;
                }
                Console.WriteLine($"{deviceType} 设备配置成功");
                Thread.Sleep(3000);
                
                // 开始采集
                if (!deviceManager.StartCollection())
                {
                    Console.WriteLine($"{deviceType} 开始采集失败");
                    return;
                }
                Console.WriteLine($"{deviceType} 开始采集成功");
                Thread.Sleep(3000);
                
                // 软件触发
                if (!deviceManager.TriggerSoftware())
                {
                    Console.WriteLine($"{deviceType} 软件触发失败");
                    return;
                }
                Console.WriteLine($"{deviceType} 软件触发成功");
                Thread.Sleep(3000);
                
            // 采集数据
            uint readSize = 49600; // 触发长度
            int channelCount = deviceManager.GetChannelCount(); // 获取设备通道数量
            byte channelMask = deviceManager.GetDefaultChannelMask(); // 获取设备默认通道掩码
            
            float[][] channelData = new float[channelCount][]; // 根据设备通道数量创建数据数组
            for (int i = 0; i < channelCount; i++)
            {
                channelData[i] = new float[readSize];
            }
            
            Console.WriteLine($"开始读取 {deviceType} 数据... (通道数量: {channelCount})");
            
            // 创建取消令牌源，用于控制线程停止
            using (var cts = new CancellationTokenSource())
            {
                Task[] tasks;
                
                // 根据设备类型选择不同的线程创建方式
                if (deviceType == DeviceType.DAQ322)
                {
                    tasks = CreateDAQ322ContinuousReadThreads(deviceManager, deviceType, channelCount, channelMask, channelData, readSize, cts.Token);
                }
                else
                {
                    tasks = CreateStandardReadThreads(deviceManager, deviceType, channelCount, channelMask, channelData, readSize, cts.Token);
                }
                
                // 等待用户输入来停止采集
                Console.WriteLine($"按任意键停止 {deviceType} 采集...");
                Console.ReadKey();
                
                // 取消所有线程
                cts.Cancel();
                
                try
                {
                    // 等待所有任务完成
                    Task.WaitAll(tasks.Where(t => t != null).ToArray());
                }
                catch (AggregateException)
                {
                    // 忽略取消导致的异常
                }
            }
                
                // 停止采集
                deviceManager.StopCollection();
                
                Console.WriteLine($"=== {deviceType} 设备测试完成 ===\n");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"测试 {deviceType} 设备时发生错误: {ex.Message}");
            }
            finally
            {
                // 清理资源
                deviceManager?.Dispose();
            }
        }

        // 创建标准读取线程（一次性读取）
        private static Task[] CreateStandardReadThreads(DeviceManager deviceManager, DeviceType deviceType, 
            int channelCount, byte channelMask, float[][] channelData, uint readSize, CancellationToken cancellationToken)
        {
            var tasks = new Task[channelCount];
            
            for (byte channel = 0; channel < channelCount; channel++)
            {
                if ((channelMask & (1 << channel)) != 0) // 检查通道是否启用
                {
                    byte currentChannel = channel; // 创建局部变量避免闭包问题
                    tasks[channel] = Task.Run(() =>
                    {
                        bool readSuccess = false;
                        while (!readSuccess && !cancellationToken.IsCancellationRequested)
                        {
                            readSuccess = deviceManager.ReadData(currentChannel, channelData[currentChannel], readSize);
                            if (readSuccess)
                            {
                                // 计算非零数据的数量
                                int validDataCount = channelData[currentChannel].Count(x => x != 0);
                                
                                Console.WriteLine($"{deviceType} 通道 {currentChannel + 1} 数据读取成功");
                                Console.WriteLine($"{deviceType} 通道 {currentChannel + 1} 总数据长度: {readSize}");
                                Console.WriteLine($"{deviceType} 通道 {currentChannel + 1} 非零数据长度: {validDataCount}");
                                
                                // 打印前10个数据点作为示例
                                Console.WriteLine($"{deviceType} 通道 {currentChannel + 1} 的前10个数据点:");
                                for (int i = 0; i < Math.Min(10, readSize); i++)
                                {
                                    Console.WriteLine($"数据点 {i}: {channelData[currentChannel][i]:F3}V");
                                }
                            }
                            else
                            {
                                Thread.Sleep(10); // 读取失败时等待10ms再试
                            }
                        }
                    }, cancellationToken);
                }
            }
            
            return tasks;
        }

        // 创建DAQ322持续读取线程
        private static Task[] CreateDAQ322ContinuousReadThreads(DeviceManager deviceManager, DeviceType deviceType, 
            int channelCount, byte channelMask, float[][] channelData, uint readSize, CancellationToken cancellationToken)
        {
            var tasks = new Task[channelCount];
            
            for (byte channel = 0; channel < channelCount; channel++)
            {
                if ((channelMask & (1 << channel)) != 0) // 检查通道是否启用
                {
                    byte currentChannel = channel; // 创建局部变量避免闭包问题
                    tasks[channel] = Task.Run(() =>
                    {
                        Console.WriteLine($"DAQ322 通道 {currentChannel + 1} 开始持续读取数据...");
                        
                        while (!cancellationToken.IsCancellationRequested)
                        {
                            bool readSuccess = deviceManager.ReadData(currentChannel, channelData[currentChannel], readSize);
                            if (readSuccess)
                            {
                                // 获取当前时间戳
                                DateTime timestamp = DateTime.Now;
                                
                                // 计算非零数据的数量
                                int validDataCount = channelData[currentChannel].Count(x => x != 0);
                                
                                Console.WriteLine($"[{timestamp:yyyy-MM-dd HH:mm:ss.fff}] DAQ322 通道 {currentChannel + 1} 数据读取成功");
                                Console.WriteLine($"[{timestamp:yyyy-MM-dd HH:mm:ss.fff}] DAQ322 通道 {currentChannel + 1} 总数据长度: {readSize}");
                                Console.WriteLine($"[{timestamp:yyyy-MM-dd HH:mm:ss.fff}] DAQ322 通道 {currentChannel + 1} 非零数据长度: {validDataCount}");
                                
                                // 打印前10个数据点和时间戳
                                Console.WriteLine($"[{timestamp:yyyy-MM-dd HH:mm:ss.fff}] DAQ322 通道 {currentChannel + 1} 的前10个数据点:");
                                for (int i = 0; i < Math.Min(10, readSize); i++)
                                {
                                    Console.WriteLine($"[{timestamp:yyyy-MM-dd HH:mm:ss.fff}] 数据点 {i}: {channelData[currentChannel][i]:F3}V");
                                }
                                
                                // 短暂延时后继续读取下一次数据
                                Thread.Sleep(100);
                            }
                            else
                            {
                                Thread.Sleep(10); // 读取失败时等待10ms再试
                            }
                        }
                        
                        Console.WriteLine($"DAQ322 通道 {currentChannel + 1} 持续读取线程已停止");
                    }, cancellationToken);
                }
            }
            
            return tasks;
        }

        // 简化的设备测试函数
        public static void TestDAQ125() => TestDevice(DeviceType.DAQ125);
        public static void TestDAQ206() => TestDevice(DeviceType.DAQ206);
        public static void TestDAQ207() => TestDevice(DeviceType.DAQ207);
        public static void TestDAQ216() => TestDevice(DeviceType.DAQ216);
        public static void TestDAQ217() => TestDevice(DeviceType.DAQ217);
        public static void TestDAQ322() => TestDevice(DeviceType.DAQ322);

        public static void Main(string[] args)
        {
            Console.WriteLine("请选择要测试的设备:");
            Console.WriteLine("1. DAQ125 (8通道)");
            Console.WriteLine("2. DAQ206 (2通道)");
            Console.WriteLine("3. DAQ207 (2通道)");
            Console.WriteLine("4. DAQ216 (4通道)");
            Console.WriteLine("5. DAQ217 (4通道)");
            Console.WriteLine("6. DAQ322 (8通道)");
            Console.WriteLine("请输入选择 (1-6):");

            var choice = Console.ReadLine();
            
            switch (choice)
            {
                case "1":
                    TestDAQ125();
                    break;
                case "2":
                    TestDAQ206();
                    break;
                case "3":
                    TestDAQ207();
                    break;
                case "4":
                    TestDAQ216();
                    break;
                case "5":
                    TestDAQ217();
                    break;
                case "6":
                    TestDAQ322();
                    break;
                default:
                    Console.WriteLine("无效选择，默认测试 DAQ217");
                    TestDAQ217();
                    break;
            }
            
            Console.WriteLine("程序结束，按任意键退出...");
            Console.ReadKey();
        }
    }
}